﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

using System.Threading;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.IO;
using System.Xml;

using P2PChat.Data;
using P2PChat.Data.Packets;
using System.Runtime.Serialization.Formatters.Binary;

namespace P2PChat.Client.UI
{
    /// <summary>
    /// WinStart.xaml 的交互逻辑
    /// </summary>
    public partial class WinStart : Window
    {
        public WinStart()
        {
            InitializeComponent();
        }

        #region 共用的成员

        #endregion

        #region 登录按钮和登录相关的成员和方法
        private Thread thread_Login = null;
        private void btn_Login_Click(object sender, RoutedEventArgs e)
        {
            if (thread_Login != null)
            {
                // 检测是否已经在运行中。
                // 实际过程中可能不应该检测出正在运行的情况，因为在登录的时候，其他操作是无法进行的
                // 即登陆过程中无法再次触发此事件。
                if (thread_Login.ThreadState == ThreadState.Running)
                {
                    thread_Login.Abort();
                }
            }

            thread_Login = new Thread(sendPacket_Login);
            thread_Login.Start();
        }

        /// <summary>
        /// 发送登录网络包
        /// </summary>
        private void sendPacket_Login()
        {
            // 封印控件
            ui_isEnable(false);
            lb_LoginProcess.Dispatcher.Invoke(new Action(() =>
            {
                lb_LoginProcess.Content = "正在处理信息";
            }));

            // 计算相关的数据
            string txt_Username_value = null;
            txt_Username.Dispatcher.Invoke(new Action(() => { txt_Username_value = txt_Username.Text.Trim(); }));

            P2PChat.Security.Hasher.MD5Hash md5 = new Security.Hasher.MD5Hash();
            string pwdHash = null;
            md5.ComputeHash(Encoding.UTF8.GetBytes(txt_Password.Password), out pwdHash);

            // 创建网络包
            P2PChat.Data.Packets.LoginPacket p = new P2PChat.Data.Packets.LoginPacket
            {
                emailAddress = txt_Username_value,
                password = pwdHash,
                listeningPort = GlobalConfig.ListeningPort,
            };

            // 将网络包序列化,通过数据流发送序列化后的数据
            NetPacket pack_Login = new NetPacket() { 
                Content = p,
                Tag = PacketTag.Login
            };
            MemoryStream ms = null;
            try
            {
                ms = new MemoryStream();
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, pack_Login);

                using (System.Net.Sockets.TcpClient c = new System.Net.Sockets.TcpClient())
                {
                    lb_LoginProcess.Dispatcher.Invoke(new Action(() =>
                    {
                        lb_LoginProcess.Content = "正在连接服务器";
                    }));

                    try
                    {
                        // 发送登陆的请求
                        c.SendTimeout = 15 * 1000;
                        c.Connect(GlobalConfig.ServerHost, GlobalConfig.ServerPort);
                        lb_LoginProcess.Dispatcher.Invoke(new Action(() =>
                        {
                            lb_LoginProcess.Content = "正在发送登录请求";
                        }));

                        // 发送数据.
                        // 标记 >> $PacketSend
                        c.Client.Send(ms.GetBuffer());
                        
                        // 接收数据包并解包
                        // 标记 << $PacketReceive
                        NetPacket packet = (NetPacket)bf.Deserialize(c.GetStream());
                        LoginResultPacket result = null;
                        if (packet.Tag == PacketTag.LoginResult) {
                            result = packet.Content as LoginResultPacket;
                        } else if (packet.Tag == PacketTag.ServerException) {
                            throw new Exception("服务器端出现了处理异常, 过程被中断.");
                        } else {
                            throw new Exception("服务器返回了不正确的数据!");
                        }

                        // 分析数据包
                        if (result.ResultCode != 0)
                        {
                            throw new Exception(result.Result);
                        }
                        else
                        {
                            lb_LoginProcess.Dispatcher.Invoke(new Action(() =>
                            {
                                lb_LoginProcess.Content = "登陆成功";
                            }));

                            // 载入个人信息和好友列表的内容。
                            if (result.personalInfo != null)
                            {
                                Data.PersonalInfo.Parse(result.personalInfo);
                            }

                            if (result.friendList != null)
                            {
                                Data.FriendList.List = result.friendList;
                            }

                            this.Dispatcher.Invoke(new Action(() =>
                            {
                                this.Close();
                            }));
                        }
                    }
                    catch (Exception ex)
                    {
                        lb_LoginProcess.Dispatcher.Invoke(new Action(() =>
                        {
                            lb_LoginProcess.Content = string.Format("登录失败：{0}", ex.Message);
                        }));
                    }
                }
            }
            catch (Exception ex)
            {

            }
            finally
            {
                if (ms != null)
                {
                    ms.Close();
                }
            }

            

            ui_isEnable(true);
        }
        #endregion

        #region 界面操作方法
        // 设定界面控件的可访问性
        private delegate void ui_isEnableDelegate(bool isEnable);
        private void ui_isEnable(bool isEnable) {
            if (!Dispatcher.CheckAccess())
            {
                Dispatcher.Invoke(new ui_isEnableDelegate(ui_isEnable), isEnable);
            }
            else
            {
                txt_Username.IsEnabled =
                    txt_Password.IsEnabled =
                    btn_Login.IsEnabled =
                    btn_Regist.IsEnabled = isEnable;
            }
        }
        #endregion

        private void btn_Regist_Click(object sender, RoutedEventArgs e)
        {
            WinRegist win_Regist = new WinRegist();
            win_Regist.ShowDialog();
        }
    }
}
